package com.fingard.dsp.bank.directbank.sdccba01;

import com.fingard.constant.Format;
import com.fingard.dsp.bank.directbank.DirectBase;
import com.fingard.net.ITcpClient;
import com.fingard.net.TcpPortClient;
import com.fingard.net.TcpReceiver;
import com.fingard.net.WebRequest;
import com.fingard.text.StringHelper;
import com.fingard.util.TransIDHelper;
import com.fingard.xml.XmlTextReader;
import com.fingard.xml.XmlTextWriter;

import java.util.Date;

/**
 * 山东城商银行联盟联盟
 * Created by cludy on 2020.4.24.
 */
public class SDCCBA01Base extends DirectBase implements ITcpClient {

    protected static TransIDHelper idHelper = new TransIDHelper(1,9999);
    protected static final String INSERTSEQ = "INSERT INTO REQSEQIDMAPPING(URID,BANKCODE,TRANSDATE,REQSEQID,BANKREQSEQID) values (?,?,?,?,?);";
    protected static final String SELECTSEQ = "SELECT BANKREQSEQID FROM REQSEQIDMAPPING WHERE REQSEQID=? AND BANKCODE=?;";

    @Override
    public void getContentLength(TcpReceiver p_receiver) throws Exception {

    }

    /**
     * 23位流水号
     * @return
     */
    protected String getQryTransID() {
        String tmpDateNow = Format.DateTime14Format.format(new Date());
        return tmpDateNow +getBankConfig().getValueAsString("bankId")
                +bankFront.loginName+idHelper.getNextIDStr();
    }

    /**
     * 报文头
     * @param xmlWriter
     * @param p_bankHeader
     * @throws Exception
     */
    protected void writeCommonHeader(XmlTextWriter xmlWriter, SDCCBA01Header p_bankHeader) throws Exception{
        xmlWriter.writeStartDocByDeclaration("<?xml version=\"1.0\" encoding=\"" + getCharset() + "\" ?>");
        xmlWriter.writeStartElement("BankData");
        xmlWriter.writeStartElement("Sign");//签名数据
        xmlWriter.writeElementString("SignedData", p_bankHeader.signedData);//签名数据
        xmlWriter.writeElementClosed("PubKey");//签名密钥
        xmlWriter.writeEndElement();
    }

    /**
     * 报文体公共部分
     * @param xmlWriter
     * @param p_bankHeader
     */
    protected void writeReqHeader(XmlTextWriter xmlWriter, SDCCBA01Header p_bankHeader){
        xmlWriter.writeStartElement("opReq");//请求报文头
        xmlWriter.writeElementString("opname", p_bankHeader.opname);//交易名
        xmlWriter.writeElementString("cstNo", bankFront.org);//客户号
        xmlWriter.writeElementString("userNo", bankFront.operator);//用户号
        xmlWriter.writeElementString("serialNo", p_bankHeader.serialNo);//交易序列号(客户端唯一标识)
        xmlWriter.writeElementString("userId", bankFront.loginName);//用户ID
        xmlWriter.writeElementString("reqTime", p_bankHeader.serialNo.substring(0,14));//客户端请求时间yyyymmddhhmmss
    }

    /**
     * 报文编码
     * @return
     */
    protected String getCharset(){
        return getBankConfig().getCharset("GBK");
    }

    /**
     * 签名编码
     * @return
     */
    protected String getSignCharset(){
        return getBankConfig().getCharset("GBK");
    }

    /**
     * 请求银行
     * @param p_reqStr
     * @return
     * @throws Exception
     */
    protected String[] sendToBank(String p_reqStr) throws Exception {
        return sendToBank(p_reqStr, "", "");
    }
    protected String[] sendToBank(String p_reqStr, String transType, String commandCode) throws Exception {
        String[] retStr = new String[]{"", ""};
        if(StringHelper.hasAnyChar(transType) && StringHelper.hasAnyChar(commandCode)) {
            this.detailSimulateForBank(bankFront.bankCode, transType, commandCode, p_reqStr, retStr);
            if (retStr[1].length() > 0) {
                return retStr;
            }
        }
        String serverURL = bankFront.serverURL;
        WriteBankLogLn("签名完成，开始请求银行\r\n1.提交银行的地址：" + serverURL);
        WriteBankLogStep2(p_reqStr);
        WebRequest tmpWebRequest = new WebRequest(serverURL);
        byte[] tmpToWriteBytes = p_reqStr.getBytes(getCharset());
        retStr = tmpWebRequest.upload(tmpToWriteBytes, getCharset());
        WriteBankLogStep3(retStr[1]);
        retStr[1]=retStr[1].substring(retStr[1].indexOf("<BankData>"));
        return retStr;
    }

    /**
     * 数据签名
     * @param opReq
     * @return
     * @throws Exception
     */
    public  String signnatrue(String opReq) throws Exception{
        String sign="";
        //先进行签名
        String[] signDatas = new String[]{"", ""};
        String signXml = String.format("<?xml version=\"1.0\" encoding=\""+getSignCharset()+"\"?>" +
                "<msg>" +
                "<msg_head>" +
                "<msg_type>0</msg_type>" +
                "<msg_id>1005</msg_id>" +
                "<msg_sn>0</msg_sn>" +
                "<version>1</version>" +
                "</msg_head>" +
                "<msg_body>" +
                //"<origin_data_len>%d</origin_data_len>" +
                "<origin_data>%s</origin_data>" +
                "</msg_body>" +
                //"</msg>", opReq.getBytes(getSignCharset()).length, opReq);
                "</msg>", opReq.replaceAll(" ","").replaceAll("\r","").replaceAll("\n",""));
        WriteBankLogLn("发送签名的报文：" + signXml);
        TcpPortClient tmpClient = new TcpPortClient(bankFront.signURL, Integer.parseInt(bankFront.signPort), this);
        TcpReceiver tmpReceiver = tmpClient.sendMessage(signXml.getBytes(getSignCharset()));
        signDatas[0] = tmpReceiver.connState;
        if (tmpReceiver.recBytes != null) {
            signDatas[1] = new String(tmpReceiver.recBytes, 0, tmpReceiver.readedLength, "GB2312");
        } else {
            signDatas[1] = tmpReceiver.getConnMsg();
        }
        WriteBankLogLn("接收签名的报文：" + signDatas[1]);
        if(signDatas[0].length()==0){
            StringBuilder tmpSbMsg = new StringBuilder();
            XmlTextReader tmpBkReader = loadBankRespXmlReader(signDatas[1], tmpSbMsg);
            if(tmpBkReader!=null){
                sign = tmpBkReader.getFirstText("/msg/msg_body/signed_data").replace("\r", "").replace("\n", "");
                WriteBankLogLn("获取签名数据为："+sign);
            }
        }
        return sign;
    }

    /**
     * 判断响应状态(全0表示成功，否则是失败)
     *
     * @param respcode 响应码
     * @return true表示成功，false失败
     */
    protected boolean success(String respcode) {
        for (int i = 0, bound = respcode.length(); i < bound; i++) {
            if (respcode.charAt(i) != '0') {
                return false;
            }
        }
        return true;
    }

    /**
     * 判断响应状态(全9表示成功，否则是失败)
     *
     * @param respcode 响应码
     * @return true表示成功，false失败
     */
    protected boolean success999(String respcode) {
        for (int i = 0, bound = respcode.length(); i < bound; i++) {
            if (respcode.charAt(i) != '9') {
                return false;
            }
        }
        return true;
    }

    /**
     * 报文头+报文体
     * @param xml
     * @return
     */
    protected String requestBody(SDCCBA01Header header, String xml) throws Exception{
        //去除报文字符串的空格换行
        String xmlIndex=xml.substring(0,xml.indexOf("encoding"));
        String xmlEnd=xml.substring(xml.indexOf("encoding"));
        xmlEnd=xmlEnd.replaceAll(" ","").replaceAll("\r","").replaceAll("\n","");
        xml=xmlIndex+xmlEnd;
        //拼接报文头和报文体
        String reqString="";
        if(StringHelper.hasAnyChar(header.serialNo) && StringHelper.hasAnyChar(header.opname) && StringHelper.hasAnyChar(xml)){
            StringBuilder head=new StringBuilder();
            head.append(addZero(header.serialNo,23)).append(addZero(header.opname,25)).append(addZero(xml.getBytes(getCharset()).length+"",8));
            reqString=head.append(xml).toString();
        }
        return reqString;
    }

    /**
     * 字符串左边补0
     * @param seqNo
     * @param length
     * @return
     */
    protected static String addZero(String seqNo,int length){
        int seqNoLength=seqNo.getBytes().length;
        if(length>seqNoLength){
            int num=length-seqNoLength;
            StringBuilder sbd=new StringBuilder();
            for(int i=0;i<num;i++){
                sbd.append("0");
            }
            seqNo=sbd.append(seqNo).toString();
        }
        return seqNo;
    }

    /**
     * 去除金额前面的0
     * @param number
     * @return
     */
    protected static String delZero(String number){
        if(!"".equals(number) && number!=null){
            number=number.replaceAll(" ","");//去除空格
            if(number.contains(".")){
                String[] money=number.split("\\.");
                if(money.length==2){
                    number=Integer.parseInt(money[0])+"."+money[1];
                }
            }else {
                number=Integer.parseInt(number)+".00";
            }
        }
        return number;
    }
}
